Skip to content

fix: audit round 2 — 57 verified defects (entry-protection hole caught live in production) - #103

Merged
yebof merged 1 commit into
mainfrom
fix/audit-round2
Jul 16, 2026
Merged

fix: audit round 2 — 57 verified defects (entry-protection hole caught live in production)#103
yebof merged 1 commit into
mainfrom
fix/audit-round2

Conversation

@yebof

@yebof yebof commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Audit round 2: 57 verified defects, including a hole caught live in production

Method

Round 1's verify fleet was cut off by the session limit with 54 findings never verified. This round: (1) verified that full backlog — 50 confirmed, 4 refuted; (2) ran 3 fresh finders over the interactions of the three PRs merged earlier today (#100/#101/#102), confirming 11 more (7 major). Every fix traces to an adversarially-verified finding with reproduction evidence.

Caught live while fixing

The first production morning on the new code (09:30 ET today) demonstrated interaction-major #1 in real time: EQNR filled within the 15s protection wait and got its GTC stop; NEE/CEG were still status=new, the old code logged "filled 0 — nothing to protect" and walked away, and both filled minutes later — naked. (Paper account; production's midday coverage-repair re-protects them.) That exact hole is fixed here: still-working entries are cancelled after the wait, the post-cancel re-read protects whatever landed, and run_intra_check now runs the coverage reconcile+repair every 30 minutes, shrinking any residual naked window from hours to ≤30 min.

Highlights by area

Entry-order lifecycle — still-working entries cancelled (protection-first); full-exit SELLs cancel the symbol's same-day entry BUYs; emergency liquidation and force_delever cancel ALL entry orders (a resting DAY buy re-bought into the crash being liquidated); coverage repair reads in-flight BUY rows; get_current_stop_price reports the highest of multiple stops; ex-div shifts EVERY stop preserving per-lot levels.

Breaker × sweeppark_excess refuses to park on a breach day (the bookend used to buy ~99% of equity into SGOV right after an emergency liquidation, and the next intra tick emergency-sold it — a deterministic all-day wash loop with spurious 🚨 pushes); force_delever unparks only what the deficit needs and records it as SWEEP_SELL (ledger isolation).

Risk/execution — non-finite cash failed cash_only OPEN (fails closed now); the executed-geometry R/R recheck also covers the raise-limit-to-market path; post-review emergency liquidation prices off fresh positions.

Data/memory/grading — earnings signal uses the structured Sentiment line + newest-filing-per-symbol + 90d recency; per-report isolation in the earnings batch; date-keyed prior-analysis pick; calibration FIFO seeds lots from full history (window bounds exits only); "recurring miss" = ≥2 separated episodes or ≥2 symbols; live-SPY leg in BUY grading; all-NaN yfinance frames route to the Alpaca fallback; business-day staleness; UTC ex-div parse; close session sees midday's own decisions.

Prompt/agent fidelity — RM finally sees equity/cash/weights (its rr_audit ran blind); allocation_pct labelled per action; reviewer entry-context no longer vanishes for positions older than today; PM sees GROSS weights; tech_analyst rejects unsolicited symbols; news close-session mode + word-boundary symbol matching; one malformed grade no longer destroys the EveningReport; PM parse failure = loud retryable analysis_error, not a fake "no_trades" hold.

Evolution/ops — quarterly snapshot's break starved Learnings for every agent; apply-from-saved-reflection lane (EVOLUTION_APPLY_SAVED) makes the human-review gate real; newline-proof guardrails; auto-commit refuses operator-dirty prompt files; the evening/meta Telegram meta lines read the real report shape (were dead code); healthcheck success pings skip intra_check (14/day pings kept the dead-man green while morning died); TELEGRAM_DISABLED accepts 1/true/yes/on.

Refuted (4)

FIFO partial-exit triple-count, sector-guidance sanitizer drop, evening grade isolation claim (misread comment), prohibited-word tripwire scenario — details in the verify transcripts.

Test plan

  • Full suite: 1430 passed (+~110 new regression tests: test_audit_round2.py, test_agents_audit_round2.py, test_ops_audit_round2.py)
  • The live NEE/CEG incident directly validates the entry-protection fix
  • Watch tomorrow's morning: still-working entries cancelled + protected; no park on any breach day

🤖 Generated with Claude Code

https://claude.ai/code/session_01PQkESoSTYx2bCy7WYnTPXR

…weep, prompt fidelity, evolution guardrails

Round 2 of the full-codebase audit: verified the 54-finding backlog the
round-1 verify fleet never reached (session limit) — 50 confirmed real, 4
refuted — plus 3 fresh finders over the interactions of today's three merged
PRs, which confirmed 11 more (7 major). One of the interaction majors was
CAUGHT LIVE during this session: the first morning on new code left NEE/CEG
naked because their entry limits were still working after the 15s protection
wait — exactly the hole fixed here.

ENTRY-ORDER LIFECYCLE (interaction majors)
- place_entry_protection treated "still working" like "terminal 0-fill" and
  walked away — a DAY entry could fill hours later with no stop watching.
  Now: still-working remainders are CANCELLED (protection-first; the
  post-cancel re-read protects whatever landed).
- No exit path cancelled a same-day resting entry BUY: a fully-exited symbol
  could re-open itself, and emergency liquidation could re-buy into the
  crash. Full-exit SELLs cancel the symbol's entry orders; emergency
  liquidation + force_delever cancel ALL entry orders first.
- Coverage repair read the last BUY under the executed-only predicate — a
  same-session 'submitted' BUY was invisible, so the belt no-op'd or applied
  a months-old stop level. get_symbol_last_buy(include_in_flight=True).
- run_intra_check now runs the coverage reconcile+repair every 30-min tick —
  the naked window for any late fill shrinks from hours to ≤30 min.
- get_current_stop_price reported whichever stop Alpaca listed first;
  multi-stop positions are now the steady state (per-BUY GTC stops). It now
  reports the HIGHEST (first to trigger) and logs multi-stop cases.
- Ex-div adjustment consolidated all stops into one level; now shifts EVERY
  stop down by the dividend, preserving per-lot geometry
  (broker.shift_stops_down with cancel/restore rollback).

BREAKER × SWEEP (interaction major)
- park_excess now refuses to park on a daily-loss-breach day (single choke
  point): the bookend used to buy ~99% of equity into SGOV right after an
  emergency liquidation, the next intra tick emergency-sold it with a
  spurious 🚨, repeating all day.
- force_delever unparks only what the deficit needs (not the whole T-bill
  balance) and records the vehicle's exit as SWEEP_SELL, preserving ledger
  isolation; recent-sells grading gets the symbol-level belt.

RISK / EXECUTION
- Non-finite cash failed the cash_only rule OPEN (NaN < 0 is False) — fails
  closed now, mirroring the NaN market_value guard.
- The R/R sanity recheck ran only when the ATR floor widened the stop; the
  raise-limit-to-market path (which shrinks reward the same way) dodged it.
  Hoisted: any execution-side geometry change re-checks R/R ≥ 1.2.
- ExecutionStage's post-review emergency liquidation priced limits off
  pre-LLM stale positions — refreshed first.

DATA / MEMORY / GRADING
- Earnings signal for missed-ops: structured Sentiment line (the naive
  "bearish" substring dropped NEUTRAL analyses), newest filing per symbol,
  90-day recency.
- One filing's failure aborted the whole earnings batch (no per-report
  isolation); prior-analysis pick was lexicographic (every 10-Q outranked
  every 10-K regardless of date).
- Calibration FIFO seeded BUY lots only from the lookback window, so a SELL
  closing an old lot matched an unrelated newer BUY; lots now seed from full
  history, the window bounds exits only.
- Missed-lessons "recurring" was auto-satisfied by one rolling-window streak;
  now ≥2 separated episodes OR ≥2 distinct symbols.
- Evening BUY grading compared a LIVE stock quote against YESTERDAY's SPY
  close (same-day buys always showed spy_pct=0); SPY leg is live now.
- get_ohlcv routed an all-NaN yfinance frame to [] without trying the Alpaca
  fallback; _staleness_days counted calendar days (every Monday read "3 days
  stale"); exDividendDate parsed in host TZ (+1 day drift on the SG host);
  correlation admitted 10-20-bar symbols as silent all-NaN matrix rows;
  close session's anti-flip-flop memory excluded the same day's midday row;
  a macro DB-write failure discarded a successful macro analysis;
  trail-cooldown wrongly ignored superseded (canceled) trail rows;
  fund_buys could report freed cash while ctx kept the stale pre-sale value.

PROMPT / AGENT FIDELITY (subagent batch)
- position_reviewer: entry stop/target lines no longer vanish for positions
  older than today; macro N/A fallbacks actually engage; grade section
  renders when only BUY grades exist; one malformed grade no longer destroys
  the whole EveningReport.
- risk_manager: prompt now carries equity/cash/per-position weights (the veto
  layer's rr_audit ran blind); allocation_pct labelled per action (BUY=% of
  portfolio, SELL=% of position).
- PM sees GROSS weights (was RAW — a "hold SQQQ" read as a 3x add);
  tech_analyst drops rows for symbols it never submitted; news_analyst
  renders mention symbols, gains a close-session mode, and word-boundary
  matches state-change symbols; meta_reflector renders watchlist_candidates.
- position_reviewer prompt no longer claims "TRAIL_STOP is always permitted"
  (the executor clamps it) or a universal SELL hard-trigger gate (it applies
  to already-trimmed symbols only).
- PM parse failure returns analysis_error (retryable, loud) instead of
  masquerading as a deliberate "no_trades" hold.

EVOLUTION / OPS (subagent batch)
- quarterly snapshot's budget `break` starved the Learnings section for
  every agent (break→continue; the hiding test now exercises the branch).
- apply-from-saved-reflection lane (EVOLUTION_APPLY_SAVED): what the human
  reviewed is exactly what gets applied — the documented gate re-ran the LLM.
- learning_text newlines defeated the line-based guardrails (normalized);
  empty apply runs leave an audit-log marker; auto-commit refuses to sweep
  operator-dirty prompt files.
- Evening/meta Telegram meta lines read the real ApplicationReport shape
  (were dead code); scheduler CronTriggers pinned to ET; healthcheck success
  pings skip intra_check (14/day pings kept the dead-man green while morning
  died); TELEGRAM_DISABLED accepts 1/true/yes/on in the wrapper.

Tests: 1430 green (+~110 new regression tests across 3 new test files).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PQkESoSTYx2bCy7WYnTPXR
@yebof
yebof merged commit 6fc3cf1 into main Jul 16, 2026
1 check passed
@yebof
yebof deleted the fix/audit-round2 branch July 16, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant